#ifndef _MCMC_FAMCE_MODEL_H
#define _MCMC_FAMCE_MODEL_H

#include "mcmcRegionModel.h"
#include "ObjectDetector.h"

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
class MCMC_FaceRect
{
public:
	// operators
	MCMC_FaceRect & operator=(const MCMC_FaceRect &a);
	
	inline	bool	InRect(const int j, const int i){return rect_face.InRect(j, i);};
public:
	irmm_Rect		rect_face;
	double			energy;
	mcmcVector<double>	vc_a_face;
	double			dmin;
	double			dmax;
};

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
class MCMC_FacePCA  
{
public:
	MCMC_FacePCA();
	virtual ~MCMC_FacePCA();

	bool LoadFromFile(const char *str_name);
	void Projection(mcmcVector<double> &vc_a, const mcmcVector<double> &vc_V);
	
	inline int		NumComponents(void){return mx_PCAs.cols();};
	inline int		SizeOfPCA(void){return mx_PCAs.rows();};
	inline int		HeightOfPCA(void){return IntClose(sqrt((long double)mx_PCAs.rows()));};
	inline int		WidthOfPCA(void){ return IntClose(sqrt((long double)mx_PCAs.rows())); };
	void			Reconstruct(mcmcVector<double> &vc_V, const mcmcVector<double> &vc_a);
	void			Reconstruct(Raster<double> &ras_image, const mcmcVector<double> &vc_a, double dmin, double dmax);
	void			Reconstruct(Raster<double> &ras_image, MCMC_FaceRect &face_rect) {Reconstruct(ras_image, face_rect.vc_a_face, face_rect.dmin, face_rect.dmax);};

	double			Prob(mcmcVector<double> &X, mcmcVector<double> *pvc_a=NULL);
	double			MatchFaceModel(Raster<float> &image_input, irmm_Rect rect_to_test, MCMC_FaceRect &face_rect);

protected:
	void			SubtractMean(mcmcVector<double> &vc_v1, mcmcVector<double> &vc_v);

protected:
	double			scale_m;
	double			scale_s;
	double			de;  // discarded energy
	mcmcVector<double>	vc_mean;
	mcmcVector<double>	vc_sigmas;
	mcmcMatrix<double>	mx_PCAs;
};

////////////////////////////////////////
////////////////////////////////////////
class MCMC_FaceParticles
{
public:
	// construction & destruction
	MCMC_FaceParticles();
	virtual ~MCMC_FaceParticles();
	void Empty(void);

	// operations
	virtual void	PrecomputeFaceModels(CFaceDetector &face_detector, Raster<float> &ras_intensity);
	virtual bool	InFaceRects(const int row, const int col);
	inline  int		NumFaceRect(void) const {return vc_precomputed_facemodels.size();};
	virtual void	ComputeFaceModel(LinkList<PMCMC_PixelSet> &list_domain, Raster<float> &ras_intensity, MCMC_FaceRect &face_rect);
	void			Reconstruct(Raster<double> &ras_image, MCMC_FaceRect &face_rect) { ras_image.SetDimension(face_rect.rect_face.Height(), face_rect.rect_face.Width()); face_pca.Reconstruct(ras_image, face_rect);};

protected:
	virtual int		BestFitRect(double darea_region, irmm_Rect bound_region);

protected:
	MCMC_FacePCA				face_pca;

	SimpleMatrix<MCMC_FaceRect>	vc_precomputed_facemodels;

	LinkList<McPoint2D>			list_center_rect;
	SimpleMatrix<irmm_Rect>		vc_biggest_center_rect;
};


/////////////////////////////////////////
// intensity model
class MCMC_Intensity_Face : public MCMC_RegionModel
{
public:
	// construction & destruction
	MCMC_Intensity_Face();
	virtual ~MCMC_Intensity_Face();
	virtual void Free(void);

	// operators
	MCMC_Intensity_Face &	 operator=(const MCMC_Intensity_Face &x);
	virtual	MCMC_Intensity_Face &	 operator=(MCMC_Model *pa);

	virtual void SaveToFile(ofstream &strm);
	virtual void ReadFromFile(ifstream &strm);

	// operations
	virtual MCMC_Model* CopyTo(void);

	virtual void	UpdateLogLikelihood(const int nlabel, MCMC_PixelSet &list_pixels_old, MCMC_PixelSet &list_pixels_new);

	virtual double	GetLogPostProb(const int j, const int i, mcmcMatrix<int> *pmx_occupied=NULL);
	virtual void	OutputInfo(char *info);
	virtual void	GetDirectValue(mcmcVector<double> &vc, const int row_pixel,const int col_pixel);
	virtual double	GetDirectDis(mcmcVector<double> &vc_pixel_value);

	virtual	void	DiffuseComputedMean(const int nlabel){;};
	virtual double	GetPdf(void);
	
	virtual void	PrepreForSynthesize(void);
	virtual bool	SynthesizeSampling(mcmcVector<double> &vc_a, const int row, const int col);
	virtual bool	Reconstruct(mcmcVector<double> &vc_a, const int row, const int col);
	
	virtual mcmcVector<double> GetAMean(void){mcmcVector<double> vc(1); vc(0)=intensity_mean; return vc;};
	virtual int	TotalCodingBits(void);

protected:
	virtual bool	MeanFromPixelSet(void);
	virtual bool	VarianceFromPixelSet(void);
	virtual bool	LogLikelihoodFromPixelSet(void);
	
public:
	double				intensity_mean;			// this mean is useless in the most cases since texture model is fixed
	double				intensity_var;
	Histogram			bin_energy;
	MCMC_ControlPoints	surface;
	MCMC_FaceRect		face_rect;

	Raster<double>		ras_reconstruct;

protected:
	RF_gaussian			rf_i;
	MCMC_FaceParticles	*pface_particles;
};




#endif
